package org.desktop.web.server;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.text.StrSubstitutor;
import org.desktop.web.client.project.service.ProjectService;
import org.desktop.web.server.util.RpcUtil;
import org.desktop.web.shared.domain.PageEntity;
import org.desktop.web.shared.domain.entities.Project;
import org.desktop.web.shared.domain.entities.SubProject;
import org.json.JSONArray;
import org.json.JSONObject;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.sencha.gxt.data.shared.SortInfo;
import com.sencha.gxt.data.shared.SortInfoBean;
import com.sencha.gxt.data.shared.loader.FilterConfig;
import com.sencha.gxt.data.shared.loader.FilterPagingLoadConfigBean;
import com.sencha.gxt.data.shared.loader.PagingLoadConfig;
import com.sencha.gxt.data.shared.loader.PagingLoadResult;
import com.sencha.gxt.data.shared.loader.PagingLoadResultBean;

public class ProjectServiceImpl extends RemoteServiceServlet implements
		ProjectService {

	private String projectses = "http://127.0.0.1:8080/timesheet/projectses";
	private String delsubprojectses = "http://127.0.0.1:8080/timesheet/subprojectses/${id}";
	private String delprojectses = "http://127.0.0.1:8080/timesheet/projectses/${id}";

	private String subProjectsByProjectId = "http://127.0.0.1:8080/timesheet/subprojectses/project/${idProject}";

	private String subprojectses = "http://127.0.0.1:8080/timesheet/subprojectses";
	private String jsonHeader = "application/json";

	@Override
	public PagingLoadResult<Project> getProjects(String token,
			PagingLoadConfig loadConfig) throws Exception {
		try {
			int activePage = (int) Math
					.ceil((double) (loadConfig.getOffset() + loadConfig
							.getLimit()) / loadConfig.getLimit());

			List<SortInfo> sorts = (List<SortInfo>) loadConfig.getSortInfo();
			StringBuilder sortUrl = new StringBuilder();
			for (int i = 0; i < sorts.size(); i++) {
				SortInfoBean sort = (SortInfoBean) sorts.get(i);
				sortUrl.append("/").append(sort.getSortField()).append("-")
						.append(sort.getSortDir());

			}
			String pagination = new StringBuilder(projectses).append("/")
					.append(activePage - 1).append("/")
					.append(loadConfig.getLimit()).append(sortUrl.toString())
					.toString();
			HttpURLConnection con = RpcUtil.getUrlConnection(
					new URL(pagination), "GET");
			if (loadConfig instanceof FilterPagingLoadConfigBean) {
				FilterPagingLoadConfigBean fp = (FilterPagingLoadConfigBean) loadConfig;
				// i filtri vanno passati attraverso un oggetto json nell'header
				// "filters"
				JSONObject jsonFilters = new JSONObject();
				List<FilterConfig> filters = fp.getFilters();
				for (Iterator iterator = filters.iterator(); iterator.hasNext();) {
					FilterConfig filterConfig = (FilterConfig) iterator.next();
					System.out.println("type:" + filterConfig.getType());

					jsonFilters.put(filterConfig.getField(),
							"%" + filterConfig.getValue() + "%");
				}
				if (jsonFilters.length() > 0) {
					con.setRequestProperty("filters", jsonFilters.toString());
				}
			}
			con.setRequestProperty("Accept", jsonHeader);
			con.setRequestProperty("token", token);

			InputStream in = con.getInputStream();

			String result = IOUtils.toString(in);

			JSONObject json = new JSONObject(result);
			ObjectMapper map = new ObjectMapper();
			PageEntity<Project> entities = map.readValue(json.toString(),
					new TypeReference<PageEntity<Project>>() {
					});
			List<Project> projects = entities.getContent();
			PagingLoadResultBean<Project> loadResult = new PagingLoadResultBean<Project>(
					projects, entities.getTotalElements(), entities.getNumber());
			return loadResult;
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		}
	}

	@Override
	public PagingLoadResult<SubProject> getSubProjectsByIdProject(String token,
			String idProject, PagingLoadConfig loadConfig) throws Exception {
		Map<String, String> valueMap = new HashMap<String, String>();
		valueMap.put("idProject", idProject);
		StrSubstitutor substitutor = new StrSubstitutor(valueMap);
		String url = substitutor.replace(subProjectsByProjectId);
		System.out.println("URL: " + url);
		URL _url = new URL(url);
		HttpURLConnection con = RpcUtil.getUrlConnection(_url, "GET");
		InputStream in = con.getInputStream();
		String jsonResult = IOUtils.toString(in);
		JSONArray json = new JSONArray(jsonResult);
		for (int i = 0; i < json.length(); i++) {
			JSONObject obj = json.getJSONObject(i);
			obj.remove("idProject");

		}
		List<SubProject> res = new ObjectMapper().readValue(json.toString(),
				new TypeReference<List<SubProject>>() {
				});

		// TODO Auto-generated method stub
		return new PagingLoadResultBean<>(res, 100, 30);
	}

	@Override
	public boolean saveSubProject(String token, int idProject, SubProject sub)
			throws Exception {

		HttpURLConnection con = RpcUtil.getUrlConnection(
				new URL(subprojectses), "POST");
		System.out.println("Calling.... " + subprojectses);
		con.setRequestProperty("Accept", jsonHeader);
		con.setRequestProperty("token", token);

		con.setRequestProperty("Content-Type", "application/octect-stream");

		ObjectMapper mapper = new ObjectMapper();
		String json = mapper.writeValueAsString(sub);
		JSONObject obj = new JSONObject(json).put("idProject",
				new JSONObject().put("id", idProject));
		System.out.println(obj.toString());

		OutputStream out = con.getOutputStream();
		out.write(obj.toString().getBytes());
		out.close();
		InputStream in = con.getInputStream();
		int responseCode = con.getResponseCode();
		System.out
				.println("ProjectServiceImpl.saveSubProject()::response code: "
						+ con.getResponseCode());
		in.close();
		return responseCode == 201;
	}

	@Override
	public boolean saveProject(Project project) throws Exception {
		HttpURLConnection con = RpcUtil.getUrlConnection(new URL(projectses),
				"POST");
		System.out.println("Calling.... " + projectses);
		con.setRequestProperty("Accept", jsonHeader);
		RpcUtil.setToken(con, getThreadLocalRequest());

		// con.setRequestProperty("token", );

		con.setRequestProperty("Content-Type", "application/octect-stream");

		ObjectMapper mapper = new ObjectMapper();
		String json = mapper.writeValueAsString(project);
		System.out.println(json);

		OutputStream out = con.getOutputStream();
		out.write(new JSONObject(json).toString().getBytes());
		out.close();
		InputStream in = con.getInputStream();
		int responseCode = con.getResponseCode();
		System.out
				.println("ProjectServiceImpl.saveSubProject()::response code: "
						+ con.getResponseCode());
		in.close();
		return responseCode == 201;
	}

	@Override
	public boolean deleteSubProject(int id) throws Exception {
		Map<String, String> map = new HashMap<String, String>();
		map.put("id", Integer.toString(id));
		StrSubstitutor sub = new StrSubstitutor(map);
		HttpURLConnection con = RpcUtil.getUrlConnection(
				new URL(sub.replace(delsubprojectses)), "DELETE");

		con.setRequestProperty("Accept", jsonHeader);
		RpcUtil.setToken(con, getThreadLocalRequest());
		InputStream in = con.getInputStream();
		int code = con.getResponseCode();
		in.close();
		// TODO Auto-generated method stub
		return code == 200;
	}

	@Override
	public boolean deleteProject(Project selectedItem) throws Exception {
		Map<String, String> map = new HashMap<String, String>();
		map.put("id", Integer.toString(selectedItem.getId()));
		StrSubstitutor sub = new StrSubstitutor(map);
		HttpURLConnection con = RpcUtil.getUrlConnection(
				new URL(sub.replace(delprojectses)), "DELETE");

		con.setRequestProperty("Accept", jsonHeader);
		RpcUtil.setToken(con, getThreadLocalRequest());
		InputStream in = con.getInputStream();
		int code = con.getResponseCode();
		in.close();
		// TODO Auto-generated method stub
		return code == 200;
	}

}
